/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2025，所有权利保留。
 * <p>
 * 项目名： cdx-ai-agent
 * 文件名： LoveApp.java
 * 模块说明：
 * 修改历史：
 * 2025年09月22日 - chendongxu - 创建。
 */
package
        com.cdx.cdxaiagent.app;


import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.document.Document;
import org.springframework.ai.rag.Query;
import org.springframework.ai.rag.preretrieval.query.expansion.MultiQueryExpander;
import org.springframework.ai.rag.preretrieval.query.transformation.CompressionQueryTransformer;
import org.springframework.ai.rag.preretrieval.query.transformation.QueryTransformer;
import org.springframework.ai.rag.preretrieval.query.transformation.RewriteQueryTransformer;
import org.springframework.ai.rag.preretrieval.query.transformation.TranslationQueryTransformer;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.dashscope.utils.Constants;
import com.cdx.cdxaiagent.advisor.MyLogAdvisor;
import com.cdx.cdxaiagent.chatmemory.MysqlBasedChatMemory;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.exception.UploadFileException;
import com.alibaba.dashscope.utils.JsonUtils;
import com.cdx.cdxaiagent.demo.TestApiKey;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;

/**
 * @author chendongxu
 * @since 1.0
 */
@Component
@Slf4j
public class LoveApp {
    public record LoveReport(String title, Integer age, List<String> suggestions) {
    }


    static {
        // 以下为北京地域url，若使用新加坡地域的模型，需将url替换为：https://dashscope-intl.aliyuncs.com/api/v1
        Constants.baseHttpApiUrl = "https://dashscope.aliyuncs.com/api/v1";
    }

    private final ChatClient chatClient;

    private final String systemPrompt;

    private final QueryTransformer queryTransformer;

    private final MultiQueryExpander queryExpander;


    private static final String SYSTEM_PROMPT = "扮演深耕恋爱心理领域的专家。开场向用户表明身份，告知用户可倾诉恋爱难题。" +
            "围绕单身、恋爱、已婚三种状态提问：单身状态询问社交圈拓展及追求心仪对象的困扰；" +
            "恋爱状态询问沟通、习惯差异引发的矛盾；已婚状态询问家庭责任与亲属关系处理的问题。" +
            "引导用户详述事情经过、对方反应及自身想法，以便给出专属解决方案。";
    @Autowired
    public LoveApp(
            ChatModel dashscopeChatModel,
            MysqlBasedChatMemory mysqlBasedChatMemory,
            @Value("${chat.system-prompt}") String systemPrompt
    ) {
        this.systemPrompt = systemPrompt;
        this.chatClient = ChatClient.builder(dashscopeChatModel)
                .defaultSystem(systemPrompt)
                .defaultAdvisors(
                        new MessageChatMemoryAdvisor(mysqlBasedChatMemory),
                        new MyLogAdvisor()
                )
                .build();
        this.queryTransformer = RewriteQueryTransformer.builder()
                .chatClientBuilder(ChatClient.builder(dashscopeChatModel))
                .build();


        this.queryExpander = MultiQueryExpander.builder()
                .chatClientBuilder(ChatClient.builder(dashscopeChatModel).defaultAdvisors(
                        new MessageChatMemoryAdvisor(mysqlBasedChatMemory),
                        new MyLogAdvisor()
                ))
                .numberOfQueries(3)
                .build();




    }
public  String ttest() {
    List<Query> queries = queryExpander.expand(new Query("啥是程序员鱼皮？他会啥？"));
    return null;
}



    public LoveReport doChatWithReport(String message, String chatId) {
        // 使用 PromptTemplate 动态渲染提示词
        PromptTemplate promptTemplate = new PromptTemplate(systemPrompt + "每次对话后都要生成恋爱结果，标题为{username},年龄为{age}的恋爱报告，内容为建议列表");
        String renderedPrompt = promptTemplate.render(Map.of("username", chatId,"age",32));

        LoveReport loveReport = chatClient
                .prompt()
                .system(renderedPrompt)
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .call()
                .entity(LoveReport.class);
        log.info("loveReport: {}", loveReport);
        return loveReport;
    }
    @Resource
    private VectorStore loveAppVectorStore;

    public String doChatWithRagLocal(String message, String chatId) {
        SearchRequest request = SearchRequest.builder()
                .query("什么是程序员鱼皮的编程导航学习网 codefather.cn？")
                .topK(5)                  // 返回最相似的5个结果
                .similarityThreshold(0.7) // 相似度阈值，0.0-1.0之间
                .filterExpression("category == 'web' AND date > '2025-05-03'")  // 过滤表达式
                .build();

        List<Document> results = loveAppVectorStore.similaritySearch(request);
        ChatResponse chatResponse = chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                // 应用知识库问答
                .advisors(new QuestionAnswerAdvisor(loveAppVectorStore))
                .call()
                .chatResponse();
        String content = chatResponse.getResult().getOutput().getText();
        log.info("content: {}", content);
        return content;
    }

    @Resource
    private Advisor loveAppRagCloudAdvisor;

    public String doChatWithRagCloud(String message, String chatId) {


        ChatResponse chatResponse = chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                // 开启日志，便于观察效果
                .advisors(new MyLogAdvisor())
                // 应用增强检索服务（云知识库服务）
                .advisors(loveAppRagCloudAdvisor)
                .call()
                .chatResponse();
        String content = chatResponse.getResult().getOutput().getText();
        log.info("content: {}", content);
        return content;
    }


    public  void call() throws ApiException, NoApiKeyException, UploadFileException, IOException {

        MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
                .content(Arrays.asList(
                        Collections.singletonMap("text", "一只灰色仓鼠在吃猫咪。")
                )).build();

        Map<String, Object> parameters = new HashMap<>();
        parameters.put("watermark", true);
        parameters.put("prompt_extend", true);
        parameters.put("negative_prompt", "");
        parameters.put("size", "1328*1328");

        MultiModalConversationParam param = MultiModalConversationParam.builder()
                .apiKey(TestApiKey.API_KEY)
                .model("qwen-image-plus")
                .messages(Collections.singletonList(userMessage))
                .parameters(parameters)
                .build();

        MultiModalConversationResult result = new MultiModalConversation().call(param);
        System.out.println(JsonUtils.toJson(result));
    }

    public String doChat(String message, String chatId) {
        ChatResponse response = chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .call()
                .chatResponse();
        return response.getResult().getOutput().getText();
    }

}

